//
// Created by Administrator on 2020/9/27.
//

#ifndef CSP_INCLUDE_UTILS_LOGDEF_H_
#define CSP_INCLUDE_UTILS_LOGDEF_H_

#include "../common/ppvaMacro.h"
#include "../common/metaMacro.h"
#include "commDef.h"

#ifdef __cplusplus
extern "C"
{
#endif

#define LOG_PARAM_SIZE_MAX   512

typedef struct CspLogItem
{
    uint16_t moduleId;
    uint16_t logLevel;
    uint16_t isMem;
    uint16_t paramSize;
    struct timeval tv;
    const char *fmtStr;
    uint16_t syncInd;
    char params[LOG_PARAM_SIZE_MAX];
} S_CspLogItem;

typedef struct CspLogInst
{
    uint32_t tick;
    const char *appTypeStr;
    uint32_t prefixLen;
    uint32_t tableSize;
    const char **moduleNameTable;
} S_CspLogInst;

extern uint32_t gCspLogLevel;

#define CSP_LOG_ARG_NUM_MAX  16
#define CSP_LOG_ARG_VALUE(i, v) \
{\
    macroCspLogArgValue[i] = 0;\
    typeof(v)* valuePtr = (typeof(v)*)(macroCspLogArgValue + i);\
    *valuePtr = v;\
}

#define CSP_LOG_COMM(md, lvl, syncInd, fmt, ...) \
do {\
    if (lvl < gCspLogLevel) {break;}\
    uint64_t macroCspLogArgValue[CSP_LOG_ARG_NUM_MAX];\
    /* 参数个数断言 */ \
    STATIC_ASSERT(PP_VA_NARG(__VA_ARGS__) <= CSP_LOG_ARG_NUM_MAX);\
    /* fmt后面的“ ”是为了强制fmt只能使用字符串常量，否则编译失败 */ \
    {const char *str = fmt " "; (void)str;}\
    /* 参数格式校验 */ \
    metamacro_if_eq(0, PP_VA_NARG(__VA_ARGS__)) (if(0) printf(fmt);)(if(0) printf(fmt, __VA_ARGS__);)\
    /* 参数展开赋值 */ \
    metamacro_if_eq(0, PP_VA_NARG(__VA_ARGS__)) (;)(metamacro_foreach(CSP_LOG_ARG_VALUE, ;, __VA_ARGS__);)\
    CSP_LogWrite(md, lvl, PP_VA_NARG(__VA_ARGS__), syncInd, fmt, macroCspLogArgValue);\
} while(0)

#define CSP_LOG_MEM_IMPL(md, lvl, ptr, size) \
do {\
    if (lvl < gCspLogLevel) {break;}\
    CSP_LogWriteMem(md, lvl, ptr, size);\
} while(0)

void CSP_LogWrite(uint32_t md, uint32_t lvl, uint32_t argc, uint32_t syncInd, const char *fmt, uint64_t value[]);
void CSP_LogWriteMem(uint32_t md, uint32_t lvl, void *ptr, uint32_t size);

#ifdef __cplusplus
}
#endif

#endif //CSP_INCLUDE_UTILS_LOGDEF_H_
